//
//  BaseModel.m
//  GMNBase
//
//  Created by DarkWorld on 2019/12/3.
//  Copyright © 2019 Mengnan Gong. All rights reserved.
//

#import "BaseModel.h"
#import <objc/runtime.h>

@implementation BaseModel

#pragma mark 安全设置
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    DLog(@"setValue--%s",__func__);
}
 
- (void)setNilValueForKey:(NSString *)key {
    DLog(@"setNilValueForKey--%s",__func__);
}

-(id)initWithDataDic:(NSDictionary*)data{
    if (self = [super init]) {
        [self setAttributes:data];
    }
    return self;
}

-(NSMutableDictionary*)attributeMapDictionary{
    NSMutableDictionary *propertyDict = [[NSMutableDictionary alloc] init];
    unsigned int outCount = 0;
    objc_property_t *properties = class_copyPropertyList(self.class, &outCount);
    for (int i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        NSString *propName = [NSString stringWithUTF8String:property_getName(property)];
        const char *typeName =property_getAttributes(property);
        NSString *properyTypeName = [[NSString alloc] initWithCString:typeName encoding:NSUTF8StringEncoding];
        [propertyDict setObject:properyTypeName forKey:propName];
    }
    return propertyDict;
}

-(SEL)getSetterSelWithAttibuteName:(NSString*)attributeName{
    NSString *capital = [[attributeName substringToIndex:1] uppercaseString];
    NSString *setterSelStr = [NSString stringWithFormat:@"set%@%@:",capital,[attributeName substringFromIndex:1]];
    return NSSelectorFromString(setterSelStr);
}
- (NSString *)customDescription{
    return nil;
}

- (NSString *)description{
     unsigned int count;
       const char *clasName    = object_getClassName(self);
       NSMutableString *string = [NSMutableString stringWithFormat:@"<%s: %p>:[ \n",clasName, self];
       Class clas              = NSClassFromString([NSString stringWithCString:clasName encoding:NSUTF8StringEncoding]);
       Ivar *ivars             = class_copyIvarList(clas, &count);
       
       for (int i = 0; i < count; i++) {
           
           @autoreleasepool {
               
               Ivar       ivar  = ivars[i];
               const char *name = ivar_getName(ivar);
               
               //得到类型
               NSString *type   = [NSString stringWithCString:ivar_getTypeEncoding(ivar) encoding:NSUTF8StringEncoding];
               NSString *key    = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
               id       value   = [self valueForKey:key];
               
               //确保BOOL值输出的是YES 或 NO
               if ([type isEqualToString:@"B"]) {
                   value = (value == 0 ? @"NO" : @"YES");
               }
               
               [string appendFormat:@"\t%@: %@\n",[self deleteUnderLine:key], value];
           }
       }
       
       [string appendFormat:@"]"];
       
       return string;
}
/// 去掉下划线
- (NSString *)deleteUnderLine:(NSString *)string{
    
    if ([string hasPrefix:@"_"]) {
        return [string substringFromIndex:1];
    }
    return string;
}
-(void)setAttributes:(NSDictionary*)dataDic{
    NSDictionary *attrMapDic = [self attributeMapDictionary];
    if (attrMapDic == nil) {
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[dataDic count]];
        for (NSString *key in dataDic) {
            [dic setValue:key forKey:key];
            attrMapDic = dic;
        }
    }
    NSEnumerator *keyEnum = [attrMapDic keyEnumerator];
    id attributeName;
    while ((attributeName = [keyEnum nextObject])) {
        SEL sel = [self getSetterSelWithAttibuteName:attributeName];
        if ([self respondsToSelector:sel]) {
            NSString *dataDicKey = [attrMapDic objectForKey:attributeName];
            id attributeValue = [dataDic objectForKey:dataDicKey];
            
            //            if (attributeValue == nil) {
            //                if ([attributeName isEqualToString:@"body"]) {
            //                    continue;
            //                }
            //                attributeValue = @"";
            //            }
            
            [self performSelectorOnMainThread:sel
                                   withObject:attributeValue
                                waitUntilDone:[NSThread isMainThread]];
        }
    }
}
- (id)initWithCoder:(NSCoder *)decoder{
     if (self = [super init]) {
           unsigned int count = 0;
           Ivar *ivarLists = class_copyIvarList([self class], &count);
           for (int i = 0; i < count; i++) {
               const char* name = ivar_getName(ivarLists[i]);
               NSString* strName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
              id value = [decoder decodeObjectForKey:strName];
               [self setValue:value forKey:strName];
           }
           free(ivarLists);
       }
       return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder{
    unsigned int count = 0;
    Ivar *ivarLists = class_copyIvarList([self class], &count);// 注意下面分析
    for (int i = 0; i < count; i++) {
        const char* name = ivar_getName(ivarLists[i]);
        NSString* strName = [NSString stringWithUTF8String:name];
        [encoder encodeObject:[self valueForKey:strName] forKey:strName];
    }
    free(ivarLists);   //一定不要忘了，自己释放。
}
- (NSData*)getArchivedData{
    return [NSKeyedArchiver archivedDataWithRootObject:self];
}

- (NSString *)cleanString:(NSString *)str {
    if (str == nil) {
        return @"";
    }
    NSMutableString *cleanString = [NSMutableString stringWithString:str];
    [cleanString replaceOccurrencesOfString:@"\n" withString:@""
                                    options:NSCaseInsensitiveSearch
                                      range:NSMakeRange(0, [cleanString length])];
    [cleanString replaceOccurrencesOfString:@"\r" withString:@""
                                    options:NSCaseInsensitiveSearch
                                      range:NSMakeRange(0, [cleanString length])];
    return cleanString;
}
- (id)copyWithZone:(NSZone *)zone
{
    id objCopy = [[[self class] allocWithZone:zone] init];
    Class clazz = [self class];
    u_int count;
    objc_property_t* properties = class_copyPropertyList(clazz, &count);
    NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
    
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        [propertyArray addObject:[NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
    }
    
    free(properties);
    for (int i = 0; i < count ; i++)
    {
        NSString *name=[propertyArray objectAtIndex:i];
        id value=[self valueForKey:name];
        if([value respondsToSelector:@selector(copyWithZone:)])
        {[objCopy setValue:[value copy] forKey:name];}
        else
        {[objCopy setValue:value  forKey:name];}
    }
    return objCopy;
}
-(id)mutableCopyWithZone:(NSZone *)zone{
    id objcopy = [[[self class]allocWithZone:zone] init];
    //    1.获取属性列表
    unsigned int count = 0;
    objc_property_t* propertylist = class_copyPropertyList([self class], &count);
    
    for (int i = 0; i < count ; i++) {
        objc_property_t property = propertylist[i];
        //    2.获取属性名
        const char * propertyName = property_getName(property);
        NSString * key = [NSString stringWithUTF8String:propertyName];
        //    3.获取属性值
        id value = [self valueForKey:key];
        //    4.判断属性值对象是否遵守NSMutableCopying协议
        if ([value respondsToSelector:@selector(mutableCopyWithZone:)]) {
            //    5.设置对象属性值
            [objcopy setValue:[value mutableCopy] forKey:key];
        }else{
            [objcopy setValue:value forKey:key];
        }
    }
    //*****切记需要手动释放
    free(propertylist);
    return objcopy;
    
}




#ifdef _FOR_DEBUG_
-(BOOL) respondsToSelector:(SEL)aSelector {
    //    printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
    return [super respondsToSelector:aSelector];
}
#endif

@end
